package com.song.server;

import com.song.enumeration.ResponseCode;
import com.song.serprovider.ServiceProvider;
import com.song.serprovider.ServiceProviderImpl;
import com.song.transport.RPCRequest;
import com.song.transport.RPCResponse;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


//通过反射进行方法调用
@Slf4j(topic = "c.MyRequestHandler")
class MyRequestHandler {

    private static final ServiceProvider serviceProvider = new ServiceProviderImpl();

    public Object handle(RPCRequest rpcRequest) throws InvocationTargetException, IllegalAccessException {
//        Object result = null;
//        try{
//            result = invokeTargetMethod(rpcRequest, service);
//            log.info("服务:{} 成功调用方法:{}", rpcRequest.getInterfaceName(), rpcRequest.getMethodName());
//
//        } catch (Exception e) {
//            log.error("调用或发送时有错误发生：", e);
//        }
//        return result;

        //使用服务端本地注册表获取服务名称 而不是原来通过全限定类名获取
        Object service = serviceProvider.getServiceProvider(rpcRequest.getInterfaceName());
        return invokeTargetMethod(rpcRequest, service);
    }

    private Object invokeTargetMethod(RPCRequest rpcRequest, Object service) throws InvocationTargetException, IllegalAccessException {
        //log.info("1111");
        Object invoke;
        Method method;//反射

        try {
            method = service.getClass().getMethod(rpcRequest.getMethodName(), rpcRequest.getParamTypes());//通过接收到的RPCRequest结构体中的方法名称 和 参数 进行 反射找到 通用接口的实现方法
            invoke = method.invoke(service, rpcRequest.getParameters());//将rpcRequest的反射得到的实际参数传入 service (HelloServiceImpl)
            log.info("Handler最终反射接口将客户端的实际参数传入service (HelloService)返回给客户端的消息为：\t" + (String) invoke);//这是调用的返回值，id = 12
            //log.info("222");
        } catch (NoSuchMethodException e) {
            log.info("服务端反射获取接口失败");
            return RPCResponse.fail(ResponseCode.METHOD_NOT_FOUND, rpcRequest.getRequestId());
        }

        return invoke;
    }
}